package io.github.kuafucv.zero.log.core.slow.request.filter;

import io.github.kuafucv.zero.log.core.match.ZeroLogAntPathMatcher;
import io.github.kuafucv.zero.log.core.slow.request.pattern.SlowRequestThreshold;
import io.github.kuafucv.zero.log.core.slow.request.pattern.SlowRequestThresholdFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class SlowRequestFilter implements Filter {

    private final Logger log = LoggerFactory.getLogger(SlowRequestFilter.class);

    private int defaultSlowTimeThreshold = 1000 ;

    private final List<SlowRequestThreshold> slowTimeThresholdList = new ArrayList<>();

    public SlowRequestFilter() {
    }

    public SlowRequestFilter(int defaultSlowTimeThreshold) {
        this.defaultSlowTimeThreshold = defaultSlowTimeThreshold;
    }

    public SlowRequestFilter(int defaultSlowTimeThreshold,SlowRequestThresholdFactory slowRequestThresholdFactory) {
        this.defaultSlowTimeThreshold = defaultSlowTimeThreshold;
        if(slowRequestThresholdFactory != null) {
            List<SlowRequestThreshold> list = slowRequestThresholdFactory.build();
            if(list != null && !list.isEmpty()) {
                for (SlowRequestThreshold slowRequestThreshold : list) {
                    String pattern = slowRequestThreshold.getUrlPattern();
                    if(pattern == null) {
                        continue;
                    }
                    pattern = pattern.trim();
                    if(pattern.isEmpty()) {
                        continue;
                    }
                    Integer timeThreshold = slowRequestThreshold.getTimeThreshold();
                    if(timeThreshold == null){
                        timeThreshold = 0;
                    }
                    SlowRequestThreshold tmp = new SlowRequestThreshold();
                    tmp.setUrlPattern(pattern);
                    tmp.setTimeThreshold(timeThreshold);
                    slowTimeThresholdList.add(tmp);
                }
            }
        }
    }

    @Override
    public void doFilter(ServletRequest request,
                         ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {

        long startTime = System.nanoTime();
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        try {
            chain.doFilter(request, response);
        } finally {
            String uri = httpRequest.getRequestURI();
            Integer timeThreshold = defaultSlowTimeThreshold;
            for (SlowRequestThreshold slowRequestThreshold : slowTimeThresholdList) {
                if(ZeroLogAntPathMatcher.matchPath(uri, slowRequestThreshold.getUrlPattern())) {
                    timeThreshold = slowRequestThreshold.getTimeThreshold();
                    break;
                }
            }
            if(timeThreshold > 0){
                long duration = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
                // 仅记录超过阈值的请求
                if (duration >= timeThreshold) {
                    logSlowRequest(httpRequest, httpResponse, duration);
                }
            }
        }
    }

    private void logSlowRequest(HttpServletRequest request,
                                HttpServletResponse response,
                                long duration) {
        // 获取请求关键信息
        String uri = request.getRequestURI();
        String method = request.getMethod();
        String remoteAddr = getClientIp(request);
        int status = response.getStatus();
        String userAgent = request.getHeader("User-Agent");
        // 构建日志消息（JSON格式）
        String logMessage = String.format(
                "{\"uri\":\"%s\",\"method\":\"%s\",\"ip\":\"%s\"," +
                        "\"status\":%d,\"duration\":%d,\"userAgent\":\"%s\"}",
                uri, method, remoteAddr, status, duration, userAgent
        );
        // 写入报送队列
        MDC.put("SLOW_REQUEST_WARN", String.valueOf(duration));
        log.warn(logMessage);
        MDC.remove("SLOW_REQUEST_WARN");
    }

    // 获取真实客户端IP（处理代理）
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip.split(",")[0]; // 处理多级代理
    }

}
